package com.coconet.gas.rest;

import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import com.coconet.gas.biz.ReportBiz;
import com.coconet.gas.biz.TaskReportRelateBiz;
import com.coconet.gas.constant.dwEnum;
import com.coconet.gas.dao.AssetsMapper;
import com.coconet.gas.dao.MeiTuoTaskipMapper;
import com.coconet.gas.dao.TaskReportRelateMapper;
import com.coconet.gas.service.TaskService;
import com.coconet.gas.service.impl.OpenvasTool2;
import com.coconet.gas.until.ScoreUtil;
import com.coconet.gas.vo.Assets;
import com.coconet.gas.vo.dw.MeiTuoTaskip;
import com.coconet.gas.vo.dw.Report;
import com.coconet.gas.vo.dw.TaskReportRelate;
import com.coconet.gas.vo.response.ExportDocxAll;
import com.gxa.entity.TaskInfoEntity;
import fr.opensagres.xdocreport.core.XDocReportException;
import fr.opensagres.xdocreport.document.IXDocReport;
import fr.opensagres.xdocreport.document.registry.XDocReportRegistry;
import fr.opensagres.xdocreport.template.IContext;
import fr.opensagres.xdocreport.template.TemplateEngineKind;
import fr.opensagres.xdocreport.template.formatter.FieldsMetadata;
import io.swagger.annotations.ApiOperation;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import org.thymeleaf.util.StringUtils;
import response.BaseResponse;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.Format;
import java.text.SimpleDateFormat;
import java.util.*;

@RestController
public class ReportRest {
    @Resource
    private ReportBiz reportBiz;
    @Resource
    private AssetsMapper assetsMapper;
    @Resource
    private MeiTuoTaskipMapper meiTuoTaskipMapper;
    @Resource
    private TaskReportRelateBiz taskReportRelateBiz;
    @Resource
    private TaskService taskService;
    @Resource
    private TaskReportRelateMapper taskReportRelateMapper;
    @Resource
    private OpenvasTool2 openvasTool;


    //每两小时自动获取漏扫报告
    @Scheduled(cron = "0 0/10 0/2 * * ?")
    public void autoGetReport() {
        List<TaskInfoEntity> tasksList = null;
        try {
            tasksList = openvasTool.getTasksList();
        } catch (Exception e) {
            e.printStackTrace();
        }
        for (TaskInfoEntity taskInfoEntity : tasksList) {
            String reportId = taskInfoEntity.getReportId();
            Report reportselect = new Report();
            reportselect.setReportId(reportId);
            //调用方法获取Report(报告) 内容
            if (taskInfoEntity.getStatus().equals("已完成")) {
                List<Report> reportList = reportBiz.selectList(reportselect);
                if (reportList.size() == 0 || reportList == null) {
                    taskService.getReportByReportId(reportId);
                }
            }
        }
    }
    @ApiOperation(value = "批量修改修复状态", httpMethod = "POST")
    @PostMapping(value = "/updateRepairStatus")
    public BaseResponse updateRepairStatus(@RequestBody List<Report> reportList) {
        for (Report report : reportList) {
            report.setRepairStatus(1);
            reportBiz.updateSelectiveById(report);
        }
        return new BaseResponse(dwEnum.SUCCEESS.code(), "");
    }

    @ApiOperation(value = "批量修改忽略状态", httpMethod = "POST")
    @PostMapping(value = "/updateIgnoreStatus")
    public BaseResponse updateIgnoreStatus(@RequestBody List<Report> reportList) {
        for (Report report : reportList) {
            report.setRepairStatus(2);
            reportBiz.updateSelectiveById(report);
        }
        return new BaseResponse(dwEnum.SUCCEESS.code(), "");
    }

    @ApiOperation(value = "扫描报告EXCEL导出", httpMethod = "POST")
    @PostMapping(value = "/exportExcel")
    public void exportEXCEL(HttpServletResponse res, @RequestBody Report report) {
        List<Report> reportList = reportBiz.selectList(report);
        Collections.sort(reportList, (p1, p2) -> Double.valueOf(p2.getSeverity()).compareTo(Double.valueOf(p1.getSeverity())));
        Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams("扫描报告", "报告"), Report.class, reportList);
        res.setHeader("Content-Disposition", "attachment;filename=" + "report.xls");
        res.setContentType("application/octet-stream");
        res.setCharacterEncoding("UTF-8");
        OutputStream os = null;
        try {
            os = res.getOutputStream();
            workbook.write(os);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @ApiOperation(value = "扫描报告docx导出", httpMethod = "POST")
    @PostMapping(value = "/exportDocx")
    public BaseResponse exportDocx(HttpServletResponse res, @RequestBody Report report) throws IOException, XDocReportException {
        res.setHeader("Content-Disposition", "attachment;filename=" + "report.docx");
        res.setContentType("application/msword");
        res.setCharacterEncoding("UTF-8");
        //获取Word模板，模板存放路径在项目的resources目录下
        InputStream ins = this.getClass().getResourceAsStream("/template.docx");
        //注册xdocreport实例并加载FreeMarker模板引擎
        IXDocReport docx = XDocReportRegistry.getRegistry().loadReport(ins,
                TemplateEngineKind.Freemarker);
        //创建xdocreport上下文对象
        IContext context = docx.createContext();

        //创建要替换的文本变量

        List<Report> reportList = taskService.getReportByReportId(report.getReportId());
        Assets assetsNow = assetsMapper.getAsset(reportList.get(0).getIp());
        if (assetsNow == null) {
            return new BaseResponse(dwEnum.FAILURE.code(), "此报告无关联资产,无法导出!");
        }
        MeiTuoTaskip meiTuoTaskipNow = meiTuoTaskipMapper.getMeitupTaskIp(reportList.get(0).getIp());

        context.put("ip", reportList.get(0).getIp());
        context.put("assetsName", changeNull(assetsNow.getAssetsname()));
        context.put("model", changeNull(assetsNow.getModel()));
        String source = new String();
        if (assetsNow.getSource().equals("1")) {
            source = "自动添加";
        } else if (assetsNow.getSource().equals("0")) {
            source = "手动添加";
        }
        context.put("source", changeNull(source));
        context.put("department", changeNull(assetsNow.getDepartment()));
        context.put("os", changeNull(meiTuoTaskipNow.getOs()));
        context.put("mac", changeNull(meiTuoTaskipNow.getMac()));
        context.put("provide", changeNull(assetsNow.getProvide()));
        context.put("assetsType", changeNull(assetsNow.getAssetstype()));
        context.put("maintain", changeNull(assetsNow.getMaintain()));
        context.put("level", changeNull(assetsNow.getLevel()));

        /*context.put("os", "");
        context.put("mac", "");
        context.put("provide", "");
        context.put("assetsType", "");
        context.put("maintain", "");
        context.put("level", "");*/

        TaskReportRelate taskReportRelate = new TaskReportRelate();
        taskReportRelate.setReportId(reportList.get(0).getReportId());
        TaskReportRelate taskReportRelateNow = taskReportRelateBiz.selectOne(taskReportRelate);
        Format format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        String scanTime = format.format(taskReportRelateNow.getReportTime());
        context.put("scanTime", scanTime);

        Integer highNum = 0;
        Integer midNum = 0;
        Integer lowNum = 0;
        Integer logNum = 0;
        for (Report reportNow : reportList) {
            reportNow.setCveName(changeNull(reportNow.getCveName()));
            reportNow.setCve(changeNull(reportNow.getCve()));
            reportNow.setPort(changeNull(reportNow.getPort()));
            reportNow.setThreat(changeNull(reportNow.getThreat()));
            reportNow.setSolution(changeNull(reportNow.getSolution()));
            if (reportNow.getThreat().equals("高")) {
                highNum++;
            } else if (reportNow.getThreat().equals("中")) {
                midNum++;
            } else if (reportNow.getThreat().equals("低")) {
                lowNum++;
            } else if (reportNow.getThreat().equals("Log")) {
                logNum++;
            }
        }
        context.put("highNum", highNum);
        context.put("midNum", midNum);
        context.put("lowNum", lowNum);
        context.put("logNum", logNum);

        context.put("score", ScoreUtil.calculationScore(highNum, midNum, lowNum, logNum));
        Collections.sort(reportList, (p1, p2) -> Double.valueOf(p2.getSeverity()).compareTo(Double.valueOf(p1.getSeverity())));
        context.put("reports", reportList);

        //创建字段元数据
        FieldsMetadata fm = docx.createFieldsMetadata();
        //Word模板中的表格数据对应的集合类型
        fm.load("reports", Report.class, true);

        //输出到本地目录
        //FileOutputStream out = new FileOutputStream(new File("D://商品销售报表.docx"));

        //导出docx
        docx.process(context, res.getOutputStream());
        return new BaseResponse(dwEnum.SUCCEESS.code(), "导出报告成功");
    }

    @ApiOperation(value = "扫描结果统计docx导出", httpMethod = "POST")
    @PostMapping(value = "/exportDocxAll")
    public void exportDocxAll(HttpServletResponse res, @RequestBody List<String> reportIdList) throws IOException, XDocReportException {
        res.setHeader("Content-Disposition", "attachment;filename=" + "reportAll.docx");
        res.setContentType("application/msword");
        res.setCharacterEncoding("UTF-8");
        //获取Word模板，模板存放路径在项目的resources目录下
        InputStream ins = this.getClass().getResourceAsStream("/templateAll.docx");
        //注册xdocreport实例并加载FreeMarker模板引擎
        IXDocReport docx = XDocReportRegistry.getRegistry().loadReport(ins,
                TemplateEngineKind.Freemarker);
        //创建xdocreport上下文对象
        IContext context = docx.createContext();
        List<ExportDocxAll> exportDocxAllList = new ArrayList<>();
        Integer highTotal = 0;
        Integer midTotal = 0;
        Integer lowTotal = 0;
        Integer logTotal = 0;
        for (String reportId : reportIdList) {
            List<Report> reportList = taskService.getReportByReportId(reportId);
            if (reportList != null && reportList.size() > 0) {
                Integer highNum = 0;
                Integer midNum = 0;
                Integer lowNum = 0;
                Integer logNum = 0;
                for (Report reportNow : reportList) {
                    if (reportNow.getThreat().equals("高")) {
                        highNum++;
                    } else if (reportNow.getThreat().equals("中")) {
                        midNum++;
                    } else if (reportNow.getThreat().equals("低")) {
                        lowNum++;
                    } else if (reportNow.getThreat().equals("Log")) {
                        logNum++;
                    }
                }
                highTotal += highNum;
                midTotal += midNum;
                lowTotal += lowNum;
                logTotal += logNum;
                Assets assetsNow = assetsMapper.getAsset(reportList.get(0).getIp());
                String score = ScoreUtil.calculationScore(highNum, midNum, lowNum, logNum);
                TaskReportRelate taskReportRelate = new TaskReportRelate();
                taskReportRelate.setReportId(reportId);
                SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//注意月份是MM
                ExportDocxAll exportDocxAll = new ExportDocxAll(reportList.get(0).getIp(), changeNull(assetsNow.getAssetsname()), highNum, midNum, lowNum, logNum, Double.valueOf(score), simpleDateFormat.format(taskReportRelateMapper.selectOne(taskReportRelate).getReportTime()));
                exportDocxAllList.add(exportDocxAll);
            }
        }
        context.put("numTotal", exportDocxAllList.size());
        context.put("highTotal", highTotal);
        context.put("midTotal", midTotal);
        context.put("lowTotal", lowTotal);
        context.put("logTotal", logTotal);
        context.put("all", exportDocxAllList);
        //创建字段元数据
        FieldsMetadata fm = docx.createFieldsMetadata();
        //Word模板中的表格数据对应的集合类型
        fm.load("all", ExportDocxAll.class, true);

        //输出到本地目录
        //FileOutputStream out = new FileOutputStream(new File("D://商品销售报表.docx"));

        //导出docx
        docx.process(context, res.getOutputStream());
    }

    public String changeNull(String param) {
        if (StringUtils.isEmpty(param)) {
            return "";
        } else {
            return param;
        }
    }

}